package com.wangzy.game;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;


import java.util.Random;

/**
 * @ProjectName: SportBS
 * @Date: 2022/8/19
 * @Desc: 精灵
 */
public class Sprite implements Game {

    private final int defualt_life_count = 1;
    protected Point point;
    protected Point pointTmp;
    protected PointF ancher;
    protected Point ancherPoint;
    public int angle;//旋转角度
    public int status;//状态
    public int type;//类型
    public int score;
    public GameRect gameRect;
    protected volatile int life = defualt_life_count;
    protected Bitmap[] frames;//所有帧
    protected Bitmap currentFrame;//当前帧`
    protected BaseGameScene gameScene;
    public String key;
    protected Rect sourceRect = new Rect();
    public boolean isAnimate = false; //是否正在动画
    public volatile boolean alive = true;
    protected SpriteContainer spriteContainer;
    private static Random random = new Random();
    protected int zorderIndex;


    void initKey() {
        this.key = String.valueOf(System.currentTimeMillis()) + ":" + hashCode();
    }

    public Sprite(Bitmap frame1, Point point, BaseGameScene gameScene) {
        this.point = point;
        this.currentFrame = frame1;
        this.frames = new Bitmap[1];
        this.frames[0] = this.currentFrame;
        this.gameScene = gameScene;
        initKey();
        initAncher();
        initRect(this.currentFrame, point, gameScene);
        this.gameScene.onSpriteBorn(this);
    }
    public Sprite(Bitmap frame1, Point point, BaseGameScene gameScene,int type) {
        this.point = point;
        this.currentFrame = frame1;
        this.frames = new Bitmap[1];
        this.frames[0] = this.currentFrame;
        this.gameScene = gameScene;
        this.type=type;
        initKey();
        initAncher();
        initRect(this.currentFrame, point, gameScene);
        this.gameScene.onSpriteBorn(this);
    }

    public Sprite(Point point, BaseGameScene gameScene, Bitmap... frames) {
        this.point = point;
        this.frames = frames;
        this.currentFrame = frames[0];
        this.gameScene = gameScene;
        initKey();
        initAncher();
        initRect(this.currentFrame, point, gameScene);
        this.gameScene.onSpriteBorn(this);
    }

    public Sprite(BaseGameScene gameScene, Bitmap... frames) {
        this.frames = frames;
        this.currentFrame = frames[0];
        this.gameScene = gameScene;
        initKey();
        initAncher();
        initRect(this.currentFrame, point, gameScene);
        this.gameScene.onSpriteBorn(this);
    }

    private void initAncher() {
        if (null == ancher) {
            ancher = new PointF(0.5f, 0.5f);
        }
    }

    public void initRect(Bitmap currentFrame, Point sourcePoint, BaseGameScene gameScene) {
        if (null != currentFrame) {
            gameRect = new GameRect();
            gameRect.width = currentFrame.getWidth();
            gameRect.height = currentFrame.getHeight();
            gameRect.left = sourcePoint.x;
            gameRect.top = sourcePoint.y;
            this.sourceRect = new Rect(0, 0, gameRect.width, gameRect.height);
        }else{
//            LogUtils.e("精灵图片维空");
        }
        gameScene.addBitmap2Pool(frames);
    }


    public boolean hurt(int hurt) {
        int left = this.life - hurt;
        this.life = (left <= 0 ? 0 : left);
        if (this.life == 0) {
            dead();
            return true;
        }
        return false;
    }

    public boolean deadNow() {
        this.life = 0;
        dead();
        return true;
    }

    public Point getFinalPoint() {

        if (null != point) {

            if (null == ancher) {
                return point;
            } else {

                if (null == ancherPoint) {
                    ancherPoint = new Point();
                }
                ancherPoint.set(point.x - (int) (gameRect.width * ancher.x), point.y - (int) (gameRect.height * ancher.y));
                gameRect.left = ancherPoint.x;
                gameRect.top = ancherPoint.y;
                gameRect.right = gameRect.left + gameRect.width;
                gameRect.bottom = gameRect.top + gameRect.height;
                return ancherPoint;
            }
        }
        return null;
    }


    public Bitmap frame() {
        return currentFrame;
    }

    public GameRect getGameRect() {
        return gameRect;
    }

    public boolean contains(Sprite sprite) {
        try {
            return this.gameRect.contains(sprite.getGameRect());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public void update(Canvas canvas, Paint paint) {
        if (alive == false) {
            return;
        }
        getFinalPoint();
        if (!inScene() || life <= 0) {
            alive = false;
            dead();
        }

        if (alive && null != currentFrame && !currentFrame.isRecycled()) {
//            canvas.drawRect(gameRect.toRect(), paint);
            canvas.drawBitmap(currentFrame, sourceRect, (Rect) gameRect.toRect(), paint);
        }

    }

    public void recyle() {
        if (null != frames) {
            for (Bitmap bitmap : frames) {
                if (null != bitmap && !bitmap.isRecycled()) {
                    bitmap.recycle();
                }
            }
        }
    }

    public boolean inScene() {
        boolean inScene = isCollision(BaseGameScene.GLOBALRECT);
        if (!inScene) {
//            LogUtils.d("精灵移除出屏幕");
        }
        return inScene;
    }


    /*
struct Rect
{
    float x1, y1;        // Point 1
    float x2, y2;        // Point 2
}
*/

    boolean crossLine(Rect r1, Rect r2) {
        float w1 = r1.right - r1.left;
        float h1 = r1.bottom - r1.top;
        float w2 = r2.right - r2.left;
        float h2 = r2.bottom - r2.top;

        float w = Math.abs((r1.left + r1.right) / 2 - (r2.left + r2.right) / 2);
        float h = Math.abs((r1.top + r1.bottom) / 2 - (r2.top + r2.bottom) / 2);

        if (w < (w1 + w2) / 2 && h < (h1 + h2) / 2) return true;
        else return false;
    }

    public boolean isCollision(Rect rect) {
        //        第一个矩形：（x1,y1),(x2,y2)
        //        第二个矩形：  (x3,y3),(x4,y4)
        //        如果满足max（x1,x3）<=min(x2,x4)&&max(y1,y3)<=min(y2,y4)，则相交。

        return crossLine(gameRect.toRect(), rect);

//        float x1 = gameRect.left;
//        float y1 = gameRect.top;
//
//        float x2 = x1 + gameRect.width;
//        float y2 = y1 + gameRect.height;
//
//        float x3 = rect.left;
//        float y3 = rect.top;
//        float x4 = rect.right;
//        float y4 = rect.bottom;
//
//        return Math.max(x1, x3) <= Math.min(x2, x4) && Math.max(y1, y3) <= Math.min(y2, y4);
//
    }


    public Sprite dead() {
        alive = false;
        remove();
        this.gameScene.onSpriteDead(this);
        return this;
    }

    public void remove() {
        getSpriteContainer().remove(getKey());
//        LogUtils.d("死亡后移除:" + getSpriteContainer().size());
//        if (null != currentFrame) {
//            this.currentFrame.recycle();
//            this.currentFrame = null;
//        }

//        if (null != frames) {
//            for (Bitmap f : frames) {
//                if (null != f && !f.isRecycled()) {
//                    f.recycle();
//                }
//            }
//        }

    }

    public void moveTo(Point targetPoint) {
        this.point.x = targetPoint.x;
        this.point.y = targetPoint.y;
    }

    ValueAnimator locationAnimation = null;

    public void animateTo(Point targetPoint, int mmSecond, Runnable start, Runnable end) {
        this.pointTmp = this.point;//保存原始点

        locationAnimation = ValueAnimator.ofFloat(0, 1);
        locationAnimation.setDuration(mmSecond);
        locationAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                isAnimate = true;
                if (null != start) {
                    start.run();
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                isAnimate = false;
                if (null != end) {
                    end.run();
                }
            }
        });
        locationAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float f = (Float) animation.getAnimatedValue();
                point.x = point.x + (int) ((targetPoint.x - pointTmp.x) * f);
                point.y = point.y + (int) ((targetPoint.y - pointTmp.y) * f);
            }
        });
        locationAnimation.start();
    }


    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public BaseGameScene getGameScene() {
        return gameScene;
    }


    public Point getPoint() {
        return point;
    }

    public void setPoint(Point point) {
        this.point = point;
    }

    public PointF getAncher() {
        return ancher;
    }

    public void setAncher(PointF ancher) {
        this.ancher = ancher;
        getFinalPoint();
    }

    public Point getAncherPoint() {
        return ancherPoint;
    }

    public void setAncherPoint(Point ancherPoint) {
        this.ancherPoint = ancherPoint;
    }

    public SpriteContainer getSpriteContainer() {
        return spriteContainer;
    }

    public void setSpriteContainer(SpriteContainer spriteContainer) {
        this.spriteContainer = spriteContainer;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getZorderIndex() {
        return zorderIndex;
    }

    public void setZorderIndex(int zorderIndex) {
        this.zorderIndex = zorderIndex;
    }

    public int getLife() {
        return life;
    }

    public void setLife(int life) {
        this.life = life;
    }

    @Override
    public void onGameEvent(BaseGameScene gameScene, int event) {

    }

    @Override
    public void onGameStart(BaseGameScene gameScene) {

    }

    @Override
    public void onGameOver(BaseGameScene gameScene) {

    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}